home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xarchie-2.0.9
/
ftp-actions.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-18
|
13KB
|
498 lines
/*
* ftp-actions.c : X/FTP interface routines for xarchie
*
* George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
* 13 May 1993: Check for NULL return from ftpNewContext().
* 27 Jul 1993: Don't use boolean AND of condition flags for XtAppAddInput().
*/
#include <stdio.h>
#include <fcntl.h> /* O_RDONLY, etc. */
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Dialog.h>
#include "config.h"
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include "db.h"
#include "appres.h"
#include "xarchie.h"
#include "selection.h"
#include "browser.h"
#include "ftp.h"
#include "view-file.h"
#include "status.h"
#include "popups.h"
#include "xutil.h"
#include "alert.h"
#include "syserr.h"
#include "debug.h"
/*
* Functions defined here
*/
void initFtpActions();
void ftpGetSelectedItems(),ftpOpenSelectedItems();
void RegisterFtpFd(),UnregisterFtpFd();
int ftpPrompt();
static void ftpSelectedItems(),countFileToGet(),countFileToOpen(),addFile();
static void ftpGetFinished(),ftpOpenOneFinished();
static void initFtpTraceWidgets();
static void ftpTraceDoneAction();
static void ftpTraceReset(),ftpTraceFunc();
static void inputCallback();
static void ftpPromptCallback();
/*
* Data defined here
*/
static char **ftpFilenames;
static int numFtpFiles;
static FtpContext *ftpCurrentContext;
static Widget ftpTraceShell,ftpTraceText;
static Boolean isPoppedUp;
static XtActionsRec actionTable[] = {
{ "ftp-trace-done", ftpTraceDoneAction },
};
/* - - - - - - - - */
/* Interface functions */
void
initFtpActions()
{
XtAppAddActions(appContext,actionTable,XtNumber(actionTable));
}
void
ftpGetSelectedItems() /* Called from getAction() */
{
ftpSelectedItems(appResources.ftpLocalDir,appResources.ftpType,
appResources.ftpPrompt,appResources.ftpStrip,
countFileToGet,NULL,ftpGetFinished);
}
void
ftpOpenSelectedItems() /* Called from openBrowser() */
{
ftpSelectedItems(tmpDirectory,"ascii",False,True,
countFileToOpen,ftpOpenOneFinished,ftpGetFinished);
}
void
ftpAbortTransfer()
{
DEBUG1("ftpAbortTransfer: ftpCurrentContext=0x%x\n",ftpCurrentContext);
ftpAbort(ftpCurrentContext);
DEBUG0("ftpAbortTransfer: done\n");
}
/* - - - - - - - - */
/*
* This function starts ftp retrieval of the items selected in the
* browser into the local directory.
*/
static void
ftpSelectedItems(local_dir,typestr,prompt,strip,
countProc,doneOneProc,doneAllProc)
char *local_dir,*typestr;
Boolean prompt,strip;
void (*countProc)();
FtpCallbackProc doneOneProc,doneAllProc;
{
char *host,*cwd;
int type;
#ifdef DEBUG
int i;
#endif
DEBUG0("ftpSelectedItems: setting files to transfer\n");
numFtpFiles = 0;
forEachSelectedItem(countProc);
if (numFtpFiles == 0) {
return;
}
ftpFilenames = (char **)XtCalloc(numFtpFiles,sizeof(char *));
numFtpFiles = 0;
forEachSelectedItem(addFile);
#ifdef DEBUG
for (i=0; i < numFtpFiles; i++)
fprintf(stderr,"ftpSelectedItems: ftpFilenames[%d] = \"%s\"\n",
i,ftpFilenames[i]);
#endif
/* Is there a host? */
if ((host=getWidgetString(hostText)) == NULL || *host == '\0') {
alert0("No host specified for transfer!");
return;
}
DEBUG1("ftpSelectedItems: host = \"%s\"\n",host);
/* Optional remote directory */
cwd = getWidgetString(locationText); /* Can be "" */
DEBUG1("ftpSelectedItems: remote dir = \"%s\"\n",cwd);
if (cwd && *cwd == '\0')
cwd = NULL;
/* Convert type to ARPA code */
if (typestr == NULL || *typestr == 'a' || *typestr == 'A')
type = TYPE_A;
else if (*typestr == 'b' || *typestr == 'B')
type = TYPE_I;
else if (*typestr == 'e' || *typestr == 'E')
type = TYPE_E;
else
type = atoi(typestr);
/* Put up the tracing window if needed */
if (appResources.ftpTrace) {
if (ftpTraceShell == NULL)
initFtpTraceWidgets();
ftpTraceReset();
isPoppedUp = True;
XtPopup(ftpTraceShell,XtGrabNone);
}
/* Get the FTP context */
ftpCurrentContext =
ftpNewContext(host,"anonymous",appResources.ftpMailAddress,
cwd,local_dir,type,strip,(numFtpFiles>1 && prompt),
FTP_GET,ftpFilenames,numFtpFiles,
(appResources.ftpTrace ? ftpTraceFunc : NULL),
doneOneProc,doneAllProc);
XtFree((char *)ftpFilenames);
/* Hostname lookup might have failed */
if (ftpCurrentContext == NULL)
return;
/* Here we go... */
setBrowserState(BROWSER_FTP);
ftpStart(ftpCurrentContext);
DEBUG0("ftpSelectedItems: done\n");
}
/* - - - - - - - - */
/* Functions called by ftpGetSelectedItems */
/*ARGSUSED*/
static void
countFileToGet(dbp,list_index) /* complains about non-files */
DbEntry *dbp;
int list_index;
{
if (dbp->type == DB_FILE) {
numFtpFiles += 1;
} else {
alert1("Can't retrieve non-file \"%s\".",dbp->name);
}
}
/*ARGSUSED*/
static void
countFileToOpen(dbp,list_index) /* doesn't complain about non-files */
DbEntry *dbp;
int list_index;
{
if (dbp->type == DB_FILE) {
numFtpFiles += 1;
}
}
/*ARGSUSED*/
static void
addFile(dbp,list_index) /* adds filename to array */
DbEntry *dbp;
int list_index;
{
if (dbp->type == DB_FILE) {
ftpFilenames[numFtpFiles++] = XtNewString(dbp->name);
}
}
/* - - - - - - - - */
/* FTP callbacks */
/*
* This function is called back when the ftp transfer is complete (for
* whatever reason).
*/
/*ARGUSED*/
static void
ftpGetFinished(ftpc)
FtpContext *ftpc;
{
DEBUG1("ftpGetFinished(0x%x)...\n",ftpc);
setBrowserState(BROWSER_READY);
ftpFreeContext(ftpc);
status0("Ready");
DEBUG0("ftpGetFinished: done\n");
}
/*
* This function is called back when a single file has been successfully
* retrieved for Open.
*/
/*ARGSUSED*/
static void
ftpOpenOneFinished(ftpc)
FtpContext *ftpc;
{
char filename[MAXPATHLEN];
DEBUG1("ftpOpenOneFinished(0x%x)...\n",ftpc);
if (ftpc->local_dir && *(ftpc->local_dir))
sprintf(filename,"%s/%s",ftpc->local_dir,ftpc->files[ftpc->this_file]);
else
strcpy(filename,ftpc->files[ftpc->this_file]);
viewFile(filename);
DEBUG0("ftpOpenOneFinished: done\n");
}
/* - - - - - - - - */
/* Routines for tracing the ftp connection in a window */
static void
initFtpTraceWidgets()
{
Widget form;
ftpTraceShell = XtCreatePopupShell("ftpTraceShell",
topLevelShellWidgetClass,
toplevel,NULL,0);
form = XtCreateManagedWidget("ftpTraceForm",formWidgetClass,
ftpTraceShell,NULL,0);
(void)XtCreateManagedWidget("ftpTraceDismissButton",commandWidgetClass,
form,NULL,0);
ftpTraceText = XtCreateManagedWidget("ftpTraceText",asciiTextWidgetClass,
form,NULL,0);
XtRealizeWidget(ftpTraceShell);
(void)XSetWMProtocols(XtDisplay(ftpTraceShell),XtWindow(ftpTraceShell),
&WM_DELETE_WINDOW,1);
}
void
setFtpTraceShellState(state)
int state;
{
if (!isPoppedUp)
return;
switch (state) {
case NormalState:
XtMapWidget(ftpTraceShell);
break;
case IconicState:
XtUnmapWidget(ftpTraceShell);
break;
}
}
/*ARGSUSED*/
static void
ftpTraceDoneAction(w,event,params,num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
isPoppedUp = False;
XtPopdown(ftpTraceShell);
}
static void
ftpTraceReset()
{
Arg args[1];
XtSetArg(args[0],XtNstring,"");
XtSetValues(ftpTraceText,args,1);
}
/*
* This function is called back from within the ftp routines to monitor
* the exchange of messages.
*/
/*ARGSUSED*/
static void
ftpTraceFunc(ftpc,who,text)
FtpContext *ftpc;
int who; /* 0 => recvd, non-0 => sent */
char *text; /* text of this message */
{
if (who)
appendWidgetText(ftpTraceText,"ftp> ");
appendWidgetText(ftpTraceText,text);
if (*(text+strlen(text)-1) != '\n')
appendWidgetText(ftpTraceText,"\n");
}
/* - - - - - - - - */
/* File descriptor registration routines: */
/*
* We need as many of these as there are file descriptors. It's
* easier to guess big than to figure out where such a magic number lives.
*/
#define NUMFDS 64
struct _ftpRegisteredFds_struct {
FtpCallbackProc proc;
FtpContext *context;
XtInputId readid,writeid;
} ftpRegisteredFds[NUMFDS];
/*
* This function is exported and used by the FTP routines to register
* a file descriptor for notification. We register it by recording the
* callback information (proc and ftpc) and telling X to register the
* fd as an external input source. When X calls back to inputCallback(),
* we use the stored information to call back to the FTP routine.
* Got that?
*/
void
RegisterFtpFd(ftpc,fd,flags,proc)
FtpContext *ftpc;
int fd,flags;
FtpCallbackProc proc;
{
DEBUG3("RegisterFtpFd: ftpc=0x%x, fd=%d, flags=%d\n",ftpc,fd,flags);
if (fd < 0 || fd >= NUMFDS) {
fprintf(stderr,"YOW! Attempt to register fd %d!\n",fd);
#ifdef DEBUG
abort();
#endif
return;
}
ftpRegisteredFds[fd].proc = proc;
ftpRegisteredFds[fd].context = ftpc;
/*
* In R4, we can't give a boolean combination of flags to XtAppAddInput().
* Even if it doesn't complain, XtRemoveInput() won't remove the fd from
* both select() masks, so we'll get the "select failed" message.
*/
switch (flags) {
case O_RDONLY:
ftpRegisteredFds[fd].readid =
XtAppAddInput(appContext,fd,(XtPointer)XtInputReadMask,
inputCallback,NULL);
ftpRegisteredFds[fd].writeid = (XtInputId)NULL;
break;
case O_WRONLY:
ftpRegisteredFds[fd].readid = (XtInputId)NULL;
ftpRegisteredFds[fd].writeid =
XtAppAddInput(appContext,fd,(XtPointer)XtInputWriteMask,
inputCallback,NULL);
break;
case O_RDWR:
ftpRegisteredFds[fd].readid =
XtAppAddInput(appContext,fd,(XtPointer)XtInputReadMask,
inputCallback,NULL);
ftpRegisteredFds[fd].writeid =
XtAppAddInput(appContext,fd,(XtPointer)XtInputWriteMask,
inputCallback,NULL);
break;
}
DEBUG2("RegisterFtpFd: done: readid=0x%x, writeid=0x%x\n",
ftpRegisteredFds[fd].readid,ftpRegisteredFds[fd].writeid);
}
/*
* Called back when X says source is ready. We call the function registered
* by the FTP routines, passing the context.
*/
/*ARGSUSED*/
static void
inputCallback(client_data,source,id)
XtPointer client_data;
int *source;
XtInputId *id;
{
if (ftpRegisteredFds[*source].proc != NULL) {
(*(ftpRegisteredFds[*source].proc))(ftpRegisteredFds[*source].context);
} else {
fprintf(stderr,"YOW! Callback for fd=%d not registered!\n",*source);
#ifdef DEBUG
abort();
#endif
}
}
/*
* This function is exported and used by the FTP routines to undo
* a previous registration.
*/
/*ARGSUSED*/
void
UnregisterFtpFd(ftpc,fd)
FtpContext *ftpc;
int fd;
{
DEBUG2("UnregisterFtpFd: ftpc=0x%x, fd=%d\n",ftpc,fd);
if (fd < 0 || fd >= NUMFDS) {
fprintf(stderr,"YOW! Attempt to unregister fd %d!\n",fd);
#ifdef DEBUG
abort();
#endif
return;
}
DEBUG2("UnregisterFtpFd: readid=0x%x, writeid=0x%x\n",
ftpRegisteredFds[fd].readid,ftpRegisteredFds[fd].writeid);
if (ftpRegisteredFds[fd].readid != (XtInputId)NULL)
XtRemoveInput(ftpRegisteredFds[fd].readid);
ftpRegisteredFds[fd].readid = (XtInputId)NULL;
if (ftpRegisteredFds[fd].writeid != (XtInputId)NULL)
XtRemoveInput(ftpRegisteredFds[fd].writeid);
ftpRegisteredFds[fd].writeid = (XtInputId)NULL;
ftpRegisteredFds[fd].proc = NULL;
ftpRegisteredFds[fd].context = NULL;
DEBUG0("UnregisterFtpFd: done\n");
}
/* - - - - - - - - */
/* Routines for prompting during FTP transfers: */
static Widget ftpPromptShell;
static int ftpPromptResult;
int
ftpPrompt(ftpc)
FtpContext *ftpc;
{
char str[256];
if (ftpPromptShell == NULL)
ftpPromptShell = createPopup("ftpPrompt",4,ftpPromptCallback);
sprintf(str,"%s %s?",
(ftpc->filecmd==FTP_GET?"GET":"PUT"),ftpc->files[ftpc->this_file]);
setPopupLabel(ftpPromptShell,"ftpPrompt",str);
popupMainLoop(ftpPromptShell);
return(ftpPromptResult);
}
/*ARGSUSED*/
static void
ftpPromptCallback(w,client_data,call_data)
Widget w;
XtPointer client_data; /* button number */
XtPointer call_data;
{
switch ((int)client_data) {
case 0: /* Yes */
ftpPromptResult = 1;
break;
case 1: /* No */
ftpPromptResult = 0;
break;
case 2: /* All */
ftpCurrentContext->prompt = 0;
ftpPromptResult = 1;
break;
case 3: /* Abort */
ftpCurrentContext->this_file = ftpCurrentContext->num_files;
ftpPromptResult = 0;
break;
}
popupDone();
}